//! 测试服务器启动和管理工具
//! 
//! 提供用于测试的Redis服务器实例管理，包括：
//! - 单机Redis服务器启动
//! - 集群Redis服务器启动
//! - 服务器生命周期管理
//! - 端口分配管理

use std::process::{Child, Command, Stdio};
use std::sync::Arc;
use tokio::sync::RwLock;
use anyhow::{Result, anyhow};
use std::time::Duration;
use tokio::time::sleep;

use super::{TestConfig, wait_for_condition};

/// 测试服务器类型
#[derive(Debug, Clone)]
pub enum ServerType {
    Simple,
    ZeroLock,
    Optimized,
    Cluster,
}

/// 测试服务器实例
pub struct TestServer {
    pub server_type: ServerType,
    pub config: TestConfig,
    pub process: Option<Child>,
    pub is_running: Arc<RwLock<bool>>,
}

impl TestServer {
    /// 创建新的测试服务器实例
    pub fn new(server_type: ServerType, config: TestConfig) -> Self {
        Self {
            server_type,
            config,
            process: None,
            is_running: Arc::new(RwLock::new(false)),
        }
    }
    
    /// 启动服务器
    pub async fn start(&mut self) -> Result<()> {
        if *self.is_running.read().await {
            return Err(anyhow!("服务器已经在运行"));
        }
        
        let binary_name = match self.server_type {
            ServerType::Simple => "simple_redis_server",
            ServerType::ZeroLock => "zero_lock_redis_server",
            ServerType::Optimized => "simple_optimized_server",
            ServerType::Cluster => "cluster_redis_server",
        };
        
        let mut cmd = Command::new(format!("./target/debug/{}", binary_name));
        cmd.stdout(Stdio::null())
           .stderr(Stdio::null());
        
        // 添加端口参数（如果支持）
        match self.server_type {
            ServerType::Cluster => {
                // 集群模式需要配置文件
                cmd.arg("--port").arg(self.config.port.to_string());
            },
            _ => {
                // 其他模式使用端口参数
                cmd.arg("--port").arg(self.config.port.to_string());
            }
        }
        
        let child = cmd.spawn()
            .map_err(|e| anyhow!("启动服务器失败: {}", e))?;
        
        self.process = Some(child);
        *self.is_running.write().await = true;
        
        // 等待服务器启动
        self.wait_for_ready().await?;
        
        Ok(())
    }
    
    /// 停止服务器
    pub async fn stop(&mut self) -> Result<()> {
        if !*self.is_running.read().await {
            return Ok(());
        }
        
        if let Some(mut child) = self.process.take() {
            child.kill().map_err(|e| anyhow!("停止服务器失败: {}", e))?;
            child.wait().map_err(|e| anyhow!("等待服务器退出失败: {}", e))?;
        }
        
        *self.is_running.write().await = false;
        Ok(())
    }
    
    /// 等待服务器就绪
    async fn wait_for_ready(&self) -> Result<()> {
        let config = self.config.clone();
        let ready = wait_for_condition(
            move || {
                let host = config.host.clone();
                let port = config.port;
                async move {
                    tokio::net::TcpStream::connect((host.as_str(), port)).await.is_ok()
                }
            },
            self.config.timeout_ms,
            100, // 每100ms检查一次
        ).await;
        
        if ready {
            Ok(())
        } else {
            Err(anyhow!("服务器启动超时"))
        }
    }
    
    /// 检查服务器是否运行
    pub async fn is_running(&self) -> bool {
        *self.is_running.read().await
    }
    
    /// 获取服务器地址
    pub fn address(&self) -> String {
        format!("{}:{}", self.config.host, self.config.port)
    }
}

impl Drop for TestServer {
    fn drop(&mut self) {
        if let Some(mut child) = self.process.take() {
            let _ = child.kill();
            let _ = child.wait();
        }
    }
}

/// 测试服务器管理器
pub struct TestServerManager {
    servers: Vec<TestServer>,
    next_port: u16,
}

impl TestServerManager {
    /// 创建新的服务器管理器
    pub fn new(start_port: u16) -> Self {
        Self {
            servers: Vec::new(),
            next_port: start_port,
        }
    }
    
    /// 分配新端口
    fn allocate_port(&mut self) -> u16 {
        let port = self.next_port;
        self.next_port += 1;
        port
    }
    
    /// 创建简单Redis服务器
    pub async fn create_simple_server(&mut self) -> Result<&TestServer> {
        let port = self.allocate_port();
        let config = TestConfig {
            port,
            ..Default::default()
        };
        
        let mut server = TestServer::new(ServerType::Simple, config);
        server.start().await?;
        
        self.servers.push(server);
        Ok(self.servers.last().unwrap())
    }
    
    /// 创建零锁Redis服务器
    pub async fn create_zero_lock_server(&mut self) -> Result<&TestServer> {
        let port = self.allocate_port();
        let config = TestConfig {
            port,
            ..Default::default()
        };
        
        let mut server = TestServer::new(ServerType::ZeroLock, config);
        server.start().await?;
        
        self.servers.push(server);
        Ok(self.servers.last().unwrap())
    }
    
    /// 创建优化Redis服务器
    pub async fn create_optimized_server(&mut self) -> Result<&TestServer> {
        let port = self.allocate_port();
        let config = TestConfig {
            port,
            ..Default::default()
        };
        
        let mut server = TestServer::new(ServerType::Optimized, config);
        server.start().await?;
        
        self.servers.push(server);
        Ok(self.servers.last().unwrap())
    }
    
    /// 创建集群Redis服务器
    pub async fn create_cluster_server(&mut self) -> Result<&TestServer> {
        let port = self.allocate_port();
        let config = TestConfig {
            port,
            ..Default::default()
        };
        
        let mut server = TestServer::new(ServerType::Cluster, config);
        server.start().await?;
        
        self.servers.push(server);
        Ok(self.servers.last().unwrap())
    }
    
    /// 停止所有服务器
    pub async fn stop_all(&mut self) -> Result<()> {
        for server in &mut self.servers {
            server.stop().await?;
        }
        self.servers.clear();
        Ok(())
    }
    
    /// 获取运行中的服务器数量
    pub async fn running_count(&self) -> usize {
        let mut count = 0;
        for server in &self.servers {
            if server.is_running().await {
                count += 1;
            }
        }
        count
    }
}

impl Drop for TestServerManager {
    fn drop(&mut self) {
        // 注意：这里不能使用async，只进行同步清理
        // 在实际使用中应该显式调用stop_all()
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    
    #[test]
    fn test_server_creation() {
        let config = TestConfig::default();
        let server = TestServer::new(ServerType::Simple, config.clone());
        
        assert_eq!(server.config.port, config.port);
        assert!(matches!(server.server_type, ServerType::Simple));
    }
    
    #[test]
    fn test_server_manager_port_allocation() {
        let mut manager = TestServerManager::new(8000);
        
        let port1 = manager.allocate_port();
        let port2 = manager.allocate_port();
        let port3 = manager.allocate_port();
        
        assert_eq!(port1, 8000);
        assert_eq!(port2, 8001);
        assert_eq!(port3, 8002);
    }
    
    #[tokio::test]
    async fn test_server_manager_creation() {
        let manager = TestServerManager::new(9000);
        assert_eq!(manager.running_count().await, 0);
    }
    
    // 注意：实际的服务器启动测试需要编译好的二进制文件
    // 这些测试应该在集成测试中进行
}